#include <vector>

#include <boost/bind.hpp>

#include <kugou/server/http/HTTPConnection.h>
#include <kugou/server/http/HTTPConnectionManager.h>

namespace kugou
{
namespace server
{
namespace http
{
HTTPConnection::HTTPConnection(boost::asio::io_service &io_service, HTTPConnectionManager &manager, HTTPRequestHandler &handler)
    : m_socket(io_service)
    , m_connectionManager(manager)
    , m_requestHandler(handler)
{
}

boost::asio::ip::tcp::socket& HTTPConnection::socket()
{
    return m_socket;
}

void HTTPConnection::start()
{
    m_socket.async_read_some(boost::asio::buffer(m_buffer),
        boost::bind(&HTTPConnection::handleRead, shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
}

void HTTPConnection::stop()
{
    m_socket.close();
}

void HTTPConnection::handleRead(const boost::system::error_code &e, std::size_t bytes_transferrd)
{
    if(!e)
    {
        boost::tribool result;
        boost::tie(result,boost::tuples::ignore) = m_requestParser.parse(
            m_request, m_buffer.data(), m_buffer.data() + bytes_transferrd);

        if(result)
        {
            m_requestHandler.handleRequest(m_request,m_reply);
            boost::asio::async_write(m_socket, m_reply.ReplyBuffers(),
                boost::bind(&HTTPConnection::handleWrite, shared_from_this(),
                    boost::asio::placeholders::error));
        }
        else if(!result)
        {
            //TODO
            /*
            m_reply = reply::stock_reply(reply::bad_request);
            boost::asio::async_write(m_socket, m_reply.ReplyBuffers(),
                boost::bind(&HTTPConnection::handleWrite, shared_from_this(),
                    boost::asio::placeholders::error));
                    */
        }
        else
        {
            m_socket.async_read_some(boost::asio::buffer(m_buffer),
                boost::bind(&HTTPConnection::handleRead, shared_from_this(),
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
        }
    }
    else if(e != boost::asio::error::operation_aborted)
    {
        m_connectionManager.stop(shared_from_this());
    }
}

void HTTPConnection::handleWrite(const boost::system::error_code& e)
{
    if(!e)
    {
        // Initiate graceful connection closure.
        boost::system::error_code ignored_ec;
        m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
    }

    if(e != boost::asio::error::operation_aborted)
    {
        m_connectionManager.stop(shared_from_this());
    }
}

} // http    
} // server
} // kugou
